let currRenderDom = null;
let currelRectification = '';
let currelRectificationLevel = '';
let resizeListener = null;
let timer = null;
let currScale = 1;
let isElRectification = false;
const autofit = {
  isAutofitRunnig: false,
  init (options = {}, isShowInitTip = true) {
    if (isShowInitTip) {
      console.log('autofit.js is running');
    }
    const {
      dw = 1920,
      dh = 1080,
      el = options.renderDom || 'body',
      resize = true,
      ignore = [],
      transition = 'none',
      delay = 0,
      limit = 0.1
    } = options;
    currRenderDom = el;
    if (isShowInitTip) {
      console.log('autofit: currRenderDom is', currRenderDom);
    }
    const dom = document.querySelector(el);
    if (!dom) {
      console.error(`autofit: '${el}' is not exist`);
      return;
    }

    const style = document.createElement('style');
    const ignoreStyle = document.createElement('style');
    style.lang = 'text/css';
    ignoreStyle.lang = 'text/css';
    style.id = 'autofit-style';
    ignoreStyle.id = 'ignoreStyle';
    style.innerHTML = 'body {overflow: hidden;}';
    const bodyEl = document.querySelector('body');
    bodyEl.appendChild(style);
    bodyEl.appendChild(ignoreStyle);
    dom.style.height = `${dh}px`;
    dom.style.width = `${dw}px`;
    dom.style.transformOrigin = '0 0';
    dom.style.overflow = 'hidden';
    keepFit(dw, dh, dom, ignore, limit);
    resizeListener = () => {
      clearTimeout(timer);
      if (delay != 0) {
        timer = setTimeout(() => {
          keepFit(dw, dh, dom, ignore, limit);
          isElRectification &&
            elRectification(currelRectification, currelRectificationLevel);
        }, delay);
      } else {
        keepFit(dw, dh, dom, ignore, limit);
        isElRectification &&
          elRectification(currelRectification, currelRectificationLevel);
      }
    };
    resize && window.addEventListener('resize', resizeListener);
    this.isAutofitRunnig = true;
    setTimeout(() => {
      dom.style.transition = `${transition}s`;
    });
  },
  off (el = 'body') {
    try {
      isElRectification = false;
      window.removeEventListener('resize', resizeListener);
      document.querySelector('#autofit-style').remove();
      const ignoreStyleDOM = document.querySelector('#ignoreStyle');
      ignoreStyleDOM && ignoreStyleDOM.remove();
      document.querySelector(currRenderDom || el).style = '';
      isElRectification && offelRectification();
    } catch (error) {
      console.error('autofit: Failed to remove normally', error);
      this.isAutofitRunnig = false;
    }
    this.isAutofitRunnig && console.log('autofit.js is off');
  }
};
function elRectification (el, level = 1) {
  if (!autofit.isAutofitRunnig) {
    console.error('autofit.js：autofit has not been initialized yet');
  }
  !el && console.error(`autofit.js：bad selector: ${el}`);
  currelRectification = el;
  currelRectificationLevel = level;
  const currEl = document.querySelectorAll(el);
  if (currEl.length == 0) {
    console.error('autofit.js：elRectification found no element');
    return;
  }
  for (const item of currEl) {
    if (!isElRectification) {
      item.originalWidth = item.clientWidth;
      item.originalHeight = item.clientHeight;
    }
    const rectification = currScale == 1 ? 1 : currScale * level;
    item.style.width = `${item.originalWidth * rectification}px`;
    item.style.height = `${item.originalHeight * rectification}px`;
    item.style.transform = `scale(${1 / currScale})`;
    item.style.transformOrigin = '0 0';
  }
  isElRectification = true;
}
function offelRectification () {
  if (!currelRectification) return;
  for (const item of document.querySelectorAll(currelRectification)) {
    item.style.width = '';
    item.style.height = '';
    item.style.transform = '';
  }
}
function keepFit (dw, dh, dom, ignore, limit) {
  const clientHeight = document.documentElement.clientHeight;
  const clientWidth = document.documentElement.clientWidth;
  currScale =
    clientWidth / clientHeight < dw / dh ? clientWidth / dw : clientHeight / dh;
  currScale = Math.abs(1 - currScale) > limit ? currScale.toFixed(2) : 1;
  const height = Math.round(clientHeight / currScale);
  const width = Math.round(clientWidth / currScale);
  dom.style.height = `${height}px`;
  dom.style.width = `${width}px`;
  dom.style.transform = `scale(${currScale})`;
  const ignoreStyleDOM = document.querySelector('#ignoreStyle');
  ignoreStyleDOM.innerHTML = '';
  for (const item of ignore) {
    let itemEl = item.el || item.dom;
    typeof item == 'string' && (itemEl = item);
    if (!itemEl) {
      console.error(`autofit: bad selector: ${itemEl}`);
      continue;
    }
    const realScale = item.scale ? item.scale : 1 / currScale;
    const realFontSize = realScale != currScale ? item.fontSize : 'autofit';
    const realWidth = realScale != currScale ? item.width : 'autofit';
    const realHeight = realScale != currScale ? item.height : 'autofit';
    const regex = new RegExp(`${itemEl}(\x20|{)`, 'gm');
    const isIgnored = regex.test(ignoreStyleDOM.innerHTML);
    if (isIgnored) {
      continue;
    }
    ignoreStyleDOM.innerHTML += `\n${itemEl} {
      transform: scale(${realScale})!important;
      transform-origin: 0 0;
      width: ${realWidth}!important;
      height: ${realHeight}!important;
    }`;
    if (realFontSize) {
      ignoreStyleDOM.innerHTML += `\n${itemEl} div ,${itemEl} span,${itemEl} a,${itemEl} * {
        font-size: ${realFontSize}px;
      }`;
    }
  }
}

export default autofit;

// 参考：https://juejin.cn/post/7231089453694009404
// 一般按照1080的设计稿开发时，直接调用autofit.init() 即可。插件会自动计算缩放后撑满浏览器窗口所需的宽高。
/**
 * 以上使用的是默认参数，可根据实际情况调整，可选参数有
  * - el：渲染的dom，默认是 "body"，必须使用id选择器
  * - dw：设计稿的宽度，默认是 1920
  * - dh：设计稿的高度，默认是 1080
  * - resize：是否监听resize事件，默认是 true
  * - ignore：忽略缩放的元素（该元素将反向缩放），参数见readme.md
  * - transition：过渡时间，默认是 0
  * - delay：默认是 0
  * - limit：默认是 0.1,当缩放阈值不大于此值时不缩放，比如设置为0.1时，0.9-1.1的
*/
